package br.com.escolaespacocrianca.fineec.business;

import java.util.GregorianCalendar;
import java.util.List;

import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;

import br.com.caelum.vraptor.ioc.Component;
import br.com.escolaespacocrianca.fineec.component.GenericBuilder;
import br.com.escolaespacocrianca.fineec.model.BaseEntity;

@Component
public abstract class EntityBusiness<T extends BaseEntity> {

	private T type;
	protected Session session;
	
	public EntityBusiness(Session session,T t) {
		this.session = session;
		this.type = t;
	}
	
	@SuppressWarnings("unchecked")
	public List<T> list() {
		
		return session.createCriteria( type.getClass()).add(Restrictions.eq("deleted", false)).list();
	}
		
	public void saveOrUpdate(T t) {
		
		session.beginTransaction();
		
		T tToUpdate = find(t.getId());
		
		if (tToUpdate == null){
			@SuppressWarnings("unchecked")
			GenericBuilder<T> builder = new GenericBuilder<T>( (Class<T>) type.getClass());
	        tToUpdate = builder.build();
		}
		
		if (tToUpdate.getId() == null){
			tToUpdate.setCreateDate(new GregorianCalendar());
		}
		tToUpdate.setUpdateDate(new GregorianCalendar());
		
		updateEntityInformations(t, tToUpdate);
		
		session.saveOrUpdate(tToUpdate);
		session.getTransaction().commit();
		session.refresh(tToUpdate);
		t = tToUpdate;
	}

	protected abstract void updateEntityInformations(T t, T tToUpdate);
	
	@SuppressWarnings("unchecked")
	public T find(Integer id) {
		if (id != null){
			
			return (T) session.createCriteria(type.getClass())
					.add(Restrictions.eq("id", id))
					.add(Restrictions.eq("deleted", false)).uniqueResult();
		
		}
		return null;
	}
	
	public void delete(T t) {
		session.beginTransaction();
		
		T tFull = find(t.getId());
		
		beforeDelete(tFull);
		tFull.delete();
		
		session.update(tFull);
		
		session.getTransaction().commit();
	}

	protected abstract void beforeDelete(T t);
	
}
